/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.workflow.service.user;

import com.google.common.base.Strings;
import com.je.bpm.core.model.config.task.TaskBasicConfigImpl;
import com.je.bpm.core.model.config.task.TaskRandomConfigImpl;
import com.je.bpm.core.model.config.task.assignment.BasicAssignmentConfigImpl;
import com.je.bpm.core.model.task.*;
import com.je.bpm.engine.task.GetTakeNodeNameUtil;
import com.je.bpm.model.shared.model.WorkFlowConfig;
import com.je.bpm.model.shared.model.impl.WorkFlowConfigImpl;
import com.je.bpm.runtime.shared.identity.BO.ParserUserBo;
import com.je.bpm.runtime.shared.identity.ResultUserParser;
import com.je.common.base.util.TreeUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.workflow.service.user.userParser.UserParser;
import com.je.workflow.service.user.userParser.UserParserFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ResultUserParserImpl implements ResultUserParser {

    public static final String RANDOM_TEAM_ID = "randomTeamUserUUID123456";

    @Autowired
    private WorkFlowUserService workFlowUserService;

    @Override
    public Object parserResultUserForNextAssignee(ParserUserBo parserUserBo) {
        Map<String, Object> result = new HashMap<>();
        KaiteBaseUserTask kaiteBaseUserTask = parserUserBo.getKaiteBaseUserTask();
        result.put("workflowConfig", buildWorkFlowConfig(kaiteBaseUserTask, parserUserBo.getMultiple()));

        List<Map<String, Object>> users = new ArrayList<>();
        //获取进入路径，根据路径获取相对应的可处理人信息
        List<BasicAssignmentConfigImpl> list = parserUserBo.getKaiteBaseUserTask().getTaskAssigneeConfig().getResource();

        if (kaiteBaseUserTask instanceof KaiteRandomUserTask) {
            for (BasicAssignmentConfigImpl basicAssignmentConfig : list) {
                Map<String, Object> user = new HashMap<>();
                //判断是否是当前节点提交过来的
                if (!parserUserBo.getDirectTask().equals(parserUserBo.getKaiteBaseUserTask().getId())) {
                    if (!Strings.isNullOrEmpty(basicAssignmentConfig.getEntryPath()) && !basicAssignmentConfig.getEntryPath().contains(parserUserBo.getDirectTask())) {
                        continue;
                    }
                }
                user.put("assignmentConfigType", basicAssignmentConfig.getConfigType() + UUID.randomUUID().toString());
                user.put("assignmentConfigTypeName", basicAssignmentConfig.getConfigTypeName());
                UserParser userParser = UserParserFactory.getUserParserByCode(basicAssignmentConfig.getConfigType());
                Boolean showCompany = true;
                Map<String, String> customerMap = new HashMap<>();
                customerMap.put("taskAssigner", parserUserBo.getTaskAssigner());
                customerMap.put("frontTaskAssigner", parserUserBo.getFrontTaskAssigner());
                customerMap.put("starterUser", parserUserBo.getStarterUser());
                JSONTreeNode jsonTreeNode = userParser.parser(parserUserBo.getUserId(), basicAssignmentConfig, kaiteBaseUserTask, showCompany,
                        parserUserBo.getBean(), parserUserBo.getProd(), parserUserBo.getMultiple(), parserUserBo.getAddOwn(), customerMap);
                if (jsonTreeNode != null) {
                    JSONTreeNode parserJsonTreeNode = parserJsonTreeNode(kaiteBaseUserTask, jsonTreeNode);
                    user.put("user", parserJsonTreeNode);
                    users.add(user);
                }
                user.put("assignmentConfigTypeName", "随机节点");
            }
        } else {

            for (BasicAssignmentConfigImpl basicAssignmentConfig : list) {
                Map<String, Object> user = new HashMap<>();
                //判断是否是当前节点提交过来的
                if (!parserUserBo.getDirectTask().equals(parserUserBo.getKaiteBaseUserTask().getId())) {
                    if (!Strings.isNullOrEmpty(basicAssignmentConfig.getEntryPath()) && !basicAssignmentConfig.getEntryPath().contains(parserUserBo.getDirectTask())) {
                        continue;
                    }
                }
                user.put("assignmentConfigType", basicAssignmentConfig.getConfigType() + UUID.randomUUID().toString());
                user.put("assignmentConfigTypeName", basicAssignmentConfig.getConfigTypeName());
                //可处理人规则定义，类型
                UserParser userParser = UserParserFactory.getUserParserByCode(basicAssignmentConfig.getConfigType());
                Boolean showCompany = true;
                Map<String, String> customerMap = new HashMap<>();
                customerMap.put("taskAssigner", parserUserBo.getTaskAssigner());
                customerMap.put("frontTaskAssigner", parserUserBo.getFrontTaskAssigner());
                customerMap.put("starterUser", parserUserBo.getStarterUser());
                JSONTreeNode jsonTreeNode = userParser.parser(parserUserBo.getUserId(), basicAssignmentConfig, kaiteBaseUserTask, showCompany,
                        parserUserBo.getBean(), parserUserBo.getProd(), parserUserBo.getMultiple(), parserUserBo.getAddOwn(), customerMap);
                if (jsonTreeNode != null) {
                    JSONTreeNode parserJsonTreeNode = parserJsonTreeNode(kaiteBaseUserTask, jsonTreeNode);
                    user.put("user", parserJsonTreeNode);
                    users.add(user);
                }
                if (kaiteBaseUserTask instanceof KaiteFixedUserTask) {
                    break;
                }
            }
        }
        result.put("users", users);
        return result;
    }

    @Override
    public Object parserResultUser(ParserUserBo parserUserBo) {
        Map<String, Object> result = new HashMap<>();
        KaiteBaseUserTask kaiteBaseUserTask = parserUserBo.getKaiteBaseUserTask();
        result.put("workflowConfig", buildWorkFlowConfig(kaiteBaseUserTask, parserUserBo.getMultiple()));

        List<Map<String, Object>> users = new ArrayList<>();
        //获取进入路径，根据路径获取相对应的可处理人信息
        List<BasicAssignmentConfigImpl> list = parserUserBo.getKaiteBaseUserTask().getTaskAssigneeConfig().getResource();

        for (BasicAssignmentConfigImpl basicAssignmentConfig : list) {
            Map<String, Object> user = new HashMap<>();
            //判断是否是当前节点提交过来的
            if (!parserUserBo.getDirectTask().equals(parserUserBo.getKaiteBaseUserTask().getId())) {
                if (!Strings.isNullOrEmpty(basicAssignmentConfig.getEntryPath()) && !basicAssignmentConfig.getEntryPath().contains(parserUserBo.getDirectTask())) {
                    continue;
                }
            }
            user.put("assignmentConfigType", basicAssignmentConfig.getConfigType() + UUID.randomUUID().toString());
            user.put("assignmentConfigTypeName", basicAssignmentConfig.getConfigTypeName());
            if (kaiteBaseUserTask instanceof KaiteRandomUserTask) {
                KaiteRandomUserTask kaiteRandomUserTask = (KaiteRandomUserTask) kaiteBaseUserTask;
                TaskRandomConfigImpl taskRandomConfig = kaiteRandomUserTask.getTaskRandomConfig();
                String teamName = taskRandomConfig.getTeamName();
                user.put("assignmentConfigTypeName", teamName);
            }
            UserParser userParser = UserParserFactory.getUserParserByCode(basicAssignmentConfig.getConfigType());
            Boolean showCompany = true;
            Map<String, String> customerMap = new HashMap<>();
            customerMap.put("taskAssigner", parserUserBo.getTaskAssigner());
            customerMap.put("frontTaskAssigner", parserUserBo.getFrontTaskAssigner());
            customerMap.put("starterUser", parserUserBo.getStarterUser());
            JSONTreeNode jsonTreeNode = userParser.parser(parserUserBo.getUserId(), basicAssignmentConfig, kaiteBaseUserTask, showCompany,
                    parserUserBo.getBean(), parserUserBo.getProd(), parserUserBo.getMultiple(), parserUserBo.getAddOwn(), customerMap);
            if (jsonTreeNode != null) {
                user.put("user", jsonTreeNode);
                users.add(user);
                continue;
            }
        }
        result.put("users", users);
        return result;
    }

    private JSONTreeNode parserJsonTreeNode(KaiteBaseUserTask kaiteBaseUserTask, JSONTreeNode jsonTreeNode) {
        JSONTreeNode jsonTreeNodeNew = TreeUtil.buildRootNode();
        JSONTreeNode jsonTreeNodeChildren = new JSONTreeNode();

        if (kaiteBaseUserTask instanceof KaiteFixedUserTask) {
            if (jsonTreeNode.getChildren() == null || jsonTreeNode.getChildren().size() == 0) {
                if (!Strings.isNullOrEmpty(jsonTreeNode.getNodeInfoType()) && jsonTreeNode.getNodeInfoType().equals("json")) {
                    ArrayList<JSONTreeNode> arrayList = new ArrayList<>();
                    arrayList.add(jsonTreeNode);
                    jsonTreeNodeNew.setChildren(arrayList);
                    return jsonTreeNodeNew;
                } else {
                    return jsonTreeNode;
                }
            } else {
                return parserJsonTreeNode(kaiteBaseUserTask, jsonTreeNode.getChildren().get(0));
            }
        } else if (kaiteBaseUserTask instanceof KaiteRandomUserTask) {
            ArrayList<JSONTreeNode> arrayList = new ArrayList<>();
            KaiteRandomUserTask kaiteRandomUserTask = (KaiteRandomUserTask) kaiteBaseUserTask;
            TaskRandomConfigImpl taskRandomConfig = kaiteRandomUserTask.getTaskRandomConfig();
            String teamName = taskRandomConfig.getTeamName();
            jsonTreeNodeChildren.setId(RANDOM_TEAM_ID);
            jsonTreeNodeChildren.setCode("randomCode");
            jsonTreeNodeChildren.setText(teamName);
            jsonTreeNodeChildren.setParent(jsonTreeNodeNew.getId());
            jsonTreeNodeChildren.setIcon("fal fa-user");
            String nodeInfo = "{\"ACCOUNT_NAME\":\"" + teamName + "\",\"sex\":\"team\"}";
            jsonTreeNodeChildren.setNodeInfo(nodeInfo);
            jsonTreeNodeChildren.setNodeType("LEAF");
            jsonTreeNodeChildren.setNodeInfoType("json");
            jsonTreeNodeChildren.setLayer(jsonTreeNodeNew.getLayer() + 1);

            arrayList.add(jsonTreeNodeChildren);
            jsonTreeNodeNew.setChildren(arrayList);
            return jsonTreeNodeNew;
        } else {
            return jsonTreeNode;
        }
    }


    @Override
    public List<String> parserResultUserToListString(Object userResult, Boolean m) {
        List<String> userIds = new ArrayList<>();
        if (userResult instanceof Map) {
            List<Map<String, Object>> list = (List<Map<String, Object>>) ((Map) userResult).get("users");
            for (Map<String, Object> userMap : list) {
                JSONTreeNode jsonTreeNode = (JSONTreeNode) userMap.get("user");
                getUserIds(userIds, jsonTreeNode, m);
            }
        }
        return userIds.stream().distinct().collect(Collectors.toList());
    }

    @Override
    public List<String> parserCirculationResultUserToListString(Object userResult) {
        List<String> resultUserIds = new ArrayList<>();
        if (userResult instanceof List) {
            List<HashMap<String, Object>> list = (List) userResult;
            List<String> userIds = new ArrayList<>();
            for (HashMap<String, Object> map : list) {
                JSONTreeNode jsonTreeNode = (JSONTreeNode) map.get("user");
                getUserIds(userIds, jsonTreeNode, true);
                resultUserIds.addAll(userIds);
            }
        }
        return resultUserIds;
    }

    private List<String> getUserIds(List<String> userIds, JSONTreeNode jsonTreeNode, Boolean m) {
        if ((!m && userIds.size() > 0) || jsonTreeNode.getChildren().size() == 0) {
            return userIds;
        }
        for (JSONTreeNode userTree : jsonTreeNode.getChildren()) {
            String nodeInfo = userTree.getNodeInfo();
            if (nodeInfo == null) {
                getUserIds(userIds, userTree, m);
            } else {
                if (!Strings.isNullOrEmpty(userTree.getNodeInfoType()) && userTree.getNodeInfoType().equals("json")) {
                    userIds.add(userTree.getId());
                    if (!m) {
                        return userIds;
                    }
                } else {
                    getUserIds(userIds, userTree, m);
                }
            }
        }
        return null;
    }

    private WorkFlowConfig buildWorkFlowConfig(KaiteBaseUserTask kaiteBaseUserTask, Boolean multiple) {
        TaskBasicConfigImpl basicConfig = kaiteBaseUserTask.getTaskBasicConfig();
        WorkFlowConfigImpl workFlowConfig = new WorkFlowConfigImpl();
        workFlowConfig.setCurrentNodeId(kaiteBaseUserTask.getId());
        if (Strings.isNullOrEmpty(kaiteBaseUserTask.getName())) {
            String nodeName = GetTakeNodeNameUtil.builder().getTakeNodeName(kaiteBaseUserTask);
            workFlowConfig.setCurrentNodeName(nodeName);
        } else {
            workFlowConfig.setCurrentNodeName(kaiteBaseUserTask.getName());
        }
        workFlowConfig.setSimpleApproval(basicConfig.getSimpleApproval() == true ? "1" : "0");
        workFlowConfig.setAsynTree(basicConfig.getAsynTree() == true ? "1" : "0");
        workFlowConfig.setSelectAll(basicConfig.getSelectAll() == true ? "1" : "0");
        workFlowConfig.setPersonnelAdjustments("1");
        if (kaiteBaseUserTask instanceof KaiteCounterSignUserTask) {
            KaiteCounterSignUserTask kaiteCounterSignUserTask = (KaiteCounterSignUserTask) kaiteBaseUserTask;
            if (kaiteCounterSignUserTask.getCounterSignConfig().isDeselectAll() &&
                    kaiteCounterSignUserTask.getCounterSignConfig().isAdjustBeforeRunning()) {
                workFlowConfig.setSelectAll("0");
            } else {
                workFlowConfig.setSelectAll("1");
            }
            if (!kaiteCounterSignUserTask.getCounterSignConfig().isAdjustBeforeRunning()) {
                workFlowConfig.setPersonnelAdjustments("0");
            }
        }
        workFlowConfig.setAudFlag(WorkFlowConfigImpl.WorkFlowAudFlag.WAIT);
        if (kaiteBaseUserTask.getLoopCharacteristics() != null && kaiteBaseUserTask.getLoopCharacteristics().isSequential()) {
            workFlowConfig.setSequential("1");
        } else {
            workFlowConfig.setSequential("0");
        }
        workFlowConfig.setType(kaiteBaseUserTask.getType());
        if (kaiteBaseUserTask instanceof KaiteMultiUserTask || kaiteBaseUserTask instanceof KaiteCounterSignUserTask) {
            workFlowConfig.setShowSequentialConfig("1");
        } else {
            workFlowConfig.setShowSequentialConfig("0");
        }
        if (multiple) {
            workFlowConfig.setMultiple("1");
        } else {
            workFlowConfig.setMultiple("0");
        }
        return workFlowConfig;
    }

    @Override
    public String getUserNameByUserId(String userId) {
        if (Strings.isNullOrEmpty(userId)) {
            return "";
        }
        return workFlowUserService.getUserNameById(userId) == null ? "" : workFlowUserService.getUserNameById(userId);
    }

    @Override
    public Boolean findAssignerContainsCurrentUser(ParserUserBo parserUserBo) {
        KaiteBaseUserTask kaiteBaseUserTask = parserUserBo.getKaiteBaseUserTask();
        //获取进入路径，根据路径获取相对应的可处理人信息
        List<BasicAssignmentConfigImpl> list = parserUserBo.getKaiteBaseUserTask().getTaskAssigneeConfig().getResource();
        for (BasicAssignmentConfigImpl basicAssignmentConfig : list) {
            //判断是否是当前节点提交过来的 进入路径不符合continue
            if (!parserUserBo.getDirectTask().equals(parserUserBo.getKaiteBaseUserTask().getId())) {
                if (!Strings.isNullOrEmpty(basicAssignmentConfig.getEntryPath()) && !basicAssignmentConfig.getEntryPath().contains(parserUserBo.getDirectTask())) {
                    continue;
                }
            }
            //可处理人规则定义，类型
            UserParser userParser = UserParserFactory.getUserParserByCode(basicAssignmentConfig.getConfigType());
            Map<String, String> customerMap = new HashMap<>();
            customerMap.put("taskAssigner", parserUserBo.getTaskAssigner());
            customerMap.put("frontTaskAssigner", parserUserBo.getFrontTaskAssigner());
            customerMap.put("starterUser", parserUserBo.getStarterUser());
            Boolean isContains = userParser.analysis(parserUserBo.getUserId(), basicAssignmentConfig, kaiteBaseUserTask,
                    parserUserBo.getBean(), parserUserBo.getProd(), customerMap);
            if (isContains) {
                return true;
            }
        }
        return false;
    }
}
